﻿using System;
using System.Collections.Generic;
using System.Linq;
 

namespace  Kaiser.Models.ViewModels
{
 
    public class ViewModel
    {
        #region Fields

        private readonly ViewModel _parent;
        private readonly Dictionary<Type, object> _modelItems;
        private readonly Dictionary<String, object> _modelKeyItems;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the ViewModel class.
        /// </summary>
        public ViewModel()
        {
            _modelItems = new Dictionary<Type, object>();
            _modelKeyItems = new Dictionary<String, object>();
        }

        /// <summary>
        /// Initializes a new instance of the ViewModel class.
        /// </summary>
        /// <param name="viewModel">ViewModel instance that is the parent of the newly create instance.</param>
        public ViewModel(ViewModel viewModel)
            : this()
        {
            _parent = viewModel;

            SyncViewModel(viewModel);
        }

        #endregion

        #region Properties

        public Site Site { get; set; }
        public UserViewModel User { get; set; }
        public string ReturnUrl { get; set; }

        #endregion

        #region Public Methods

        public void AddModelItem(object modelItem)
        {
            if (modelItem != null)
                _modelItems[modelItem.GetType()] = modelItem;
        }
        public T GetModelItem<T>() where T : class
        {
            return GetModelItem(typeof(T)) as T;
        }
        public object GetModelItem(Type type)
        {
            if (_modelItems.ContainsKey(type))
            {
                return _modelItems[type];
            }

            return null;
        }

        public void AddModelItem(string key, object modelItem)
        {
            if (modelItem != null)
                _modelKeyItems[key] = modelItem;
        }
        public T GetModelItem<T>(string key) where T : class
        {
            return GetModelItem(key, typeof(T)) as T;
        }
        public object GetModelItem(string key, Type type)
        {
            if (_modelKeyItems.ContainsKey(key))
            {
                object val = _modelKeyItems[key];
                if (val == null || !type.IsAssignableFrom(val.GetType())) return null;

                return val;
            }

            return null;
        }
        public object GetModelItem(string key)
        {
            if (_modelKeyItems.ContainsKey(key))
            {
                return _modelKeyItems[key];
            }

            return null;
        }
        private IEnumerable<Type> getModelItemTypes()
        {
            return _modelItems.Select(kvp => kvp.Key);
        }

        public void RemoveModelItem(Type type)
        {
            if (getModelItemTypes().Any(t => t == type))
                _modelItems.Remove(type);
        }

        public void RemoveModelItem<T>() where T : class
        {
            RemoveModelItem(typeof(T));
        }

        /// <summary>
        /// Set all the properties of the ViewModel to the properties of the given ViewModel instance.
        /// </summary>
        /// <param name="viewModel">ViewModel to use for setting all the properties of the current ViewModel.</param>
        protected void SyncViewModel(ViewModel viewModel)
        {
            if (viewModel == null) return;

            Site = viewModel.Site;
            User = viewModel.User;
            ReturnUrl = viewModel.ReturnUrl;

            _modelItems.Clear();
            //viewModel.getModelItemTypes().ToList().ForEach(mit => AddModelItem(viewModel.GetModelItem(mit)));

            _modelKeyItems.Clear();
            foreach (var item in viewModel._modelKeyItems)
            {
                AddModelItem(item.Key, item.Value);
            }
        }

        #endregion
    }
}
